﻿(defmacro! defun! (fn* [name params body] (list 'def! name (list 'fn* params body))))

(defmacro! cond (fn* [& xs] 
  (if (> (count xs) 0) 
    (list 'if (first xs) 
      (if (> (count xs) 1) 
        (nth xs 1) 
        (throw "odd number of forms to cond")) 
      (cons 'cond (rest (rest xs)))))))

(defun! not [cond] (if cond false true))

(defmacro! set! (fn* [& xs] 
  (if (> (count xs) 0) 
    (list 'do
      (list 'def! (first xs) 
        (if (> (count xs) 1) 
          (nth xs 1) 
          (throw "odd number of forms to set!")))
      (cons 'set! (rest (rest xs)))
      nil))))

(defun! inc [x] (+ x 1))
(defun! dec [x] (- x 1))

;; mut containers
(def! mut-list
  (fn* [xs]
    (vec (map (fn* (x) (atom x)) xs))))

(def! mut-vec
  (fn* [xs]
    (vec (mut-list xs))))

(def! mut-map
  (fn* [xs]
    (vec (mut-list xs))))

;; mut options
(def! m-set
  (fn* [v n val]
    (cond
      (vector? v)
      (reset! (nth v n) val))))

(def! m-get
  (fn* [v n]
    (cond
      (vector? v)
      (deref (nth v n)))))
